home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / ClutFade 1.3.2 / C / clut_fade 1.3.2 source & libs / fade.c < prev    next >
Text File  |  1996-04-23  |  11KB  |  336 lines

  1. /********************************************************************************
  2.  
  3.      PROJECT:    clut_fade.π
  4.      
  5.      FILE:        fade.c
  6.      
  7.      PURPOSE:    'clut' fading functions
  8.      
  9.      ??/??/93    1.0 written by N. Jonas Englund
  10.      07/26/94    1.1 Changes by Mark Womack to allow fading all monitors, only the
  11.                  main monitor, or all monitors except the main monitor.  Cleaned 
  12.                  up the fade.h to hide more structures, and removed almost all global
  13.                  space used (My changes grew the global space by 10 times so I figured
  14.                  it needed to be fixed).  Current code is limited to 10 monitors max,
  15.                  but is easily cofigurable for more if you think you need it.
  16.      10/21/94    Changes by Mark Womack to make pascal friendly, fix < 256 color
  17.                  crasher, cleaned up to make more readable.
  18.      10/24/94    Integrated fade_to_clut function written by Macneil Shonle.
  19.                  Added copy_gdevice_clut function to make it easier to save
  20.                  and restore device clut's.
  21.                   Added fade_to_color function which uses both the fade_to_clut
  22.                   and copy_gdevice_clut functions to fade to a given rgb value.
  23.       04/22/96    Fixed bug found by David Padilla. Fade routines changed the ctSeed
  24.                   value of color tables, which slows subsequent calls to CopyBits.
  25.                   Now restore or set the ctSeed value back to original value.
  26.                 
  27.      =-=-= PLEASE SEE THE README THAT ACCOMPANIED THIS PROJECT FOR DETAILS =-=-=
  28.      
  29.      This software is considered Public Domain. You are free to use it in any
  30.      manner you wish. You are free to upload it to your favorite service, but
  31.      you must post it with the accompanying readme and description files.
  32.      If you use or appreciate it, please let us know!! We all love to get email.
  33.      See the addresses below.
  34.      
  35.      This software is offered 'as is'. The authors are not responsible for any
  36.      damages caused by bugs or defects that might be lurking. But if it blows up
  37.      your monitor, please let us know. If you find any bugs, problems, enhancements,
  38.      please contact us.
  39.      
  40.      Email Addresses:  MarkWomack@aol.com, MacneilS@aol.com, KenLong@aol.com.
  41.  
  42.  ********************************************************************************/
  43.  
  44. //================================= INCLUDES ====================================
  45.  
  46. #include "fade.h"
  47.  
  48. //================================= DEFINES =====================================
  49.  
  50. #define     MAXCOLORS     256     // supports 256 colors max
  51. #define        gMaxDevices    10        // supports only 10 monitors max
  52.  
  53. //================================= TYPEDEFS ====================================
  54.  
  55. typedef struct FadeValues
  56. {
  57.     short    reds[MAXCOLORS];
  58.     short    greens[MAXCOLORS];
  59.     short    blues[MAXCOLORS];
  60. }
  61. FadeValues;
  62.  
  63. //================================= FUNCTIONS ===================================
  64.  
  65. static void copy_cluts    (GDHandle, CTabHandle*, CTabHandle*, short);
  66. static void calc_fade    (long, CTabHandle, FadeValues*);
  67. static void fade_out    (long, CTabHandle, FadeValues);
  68. static void fade_in        (long, CTabHandle, CTabHandle, FadeValues);
  69. static void black_out    (CTabHandle);
  70. static void restore_clut(CTabHandle, CTabHandle);
  71.  
  72. //===== PUBLIC FUNCTIONS =====//
  73.  
  74. /********************************** fade_to_black ******************************/
  75. pascal void fade_to_black(long numSteps, short fadeFlags, Boolean fadeOut)
  76. {
  77. GDHandle     oldDev, hGD;
  78. GDHandle    gdHdls[gMaxDevices];    // list of valid graphic devices
  79. FadeValues    rgbs[gMaxDevices];        // fade values
  80. CTabHandle     gFade[gMaxDevices],        // 'clut' to alter with fading functions
  81.             gOrig[gMaxDevices];        // 'clut' to hold a copy of original
  82. short        x,numDevices,stepCount;
  83.     
  84.     // initialize
  85.     oldDev = GetGDevice();
  86.     hGD = (!!(fadeFlags & fadeMainOnly != 0)) ? GetMainDevice() : GetDeviceList();
  87.     numDevices = 0;
  88.     
  89.     // make a list of the affected gdevices
  90.     while (hGD && numDevices < gMaxDevices)
  91.     {
  92.         // skip main device if fadeAllButMain flag
  93.         if (TestDeviceAttribute(hGD,mainScreen) && (!!(fadeFlags & fadeAllButMain)))
  94.         {
  95.             hGD = (GDHandle)(*hGD)->gdNextGD;
  96.             continue;
  97.         }
  98.         
  99.         if (TestDeviceAttribute(hGD,screenDevice))
  100.         {
  101.             gdHdls[numDevices] = hGD;
  102.             numDevices++;
  103.         }
  104.  
  105.         // stop now if only fading main device
  106.         if (!!(fadeFlags & fadeMainOnly != 0))
  107.             break;
  108.             
  109.         hGD = (GDHandle)(*hGD)->gdNextGD;
  110.     }
  111.     
  112.     // calculate the fade cluts for each device
  113.     for (x = 0; x < numDevices; x++)
  114.     {            
  115.         SetGDevice(gdHdls[x]);
  116.         copy_cluts(gdHdls[x], &gFade[x], &gOrig[x], x);
  117.         calc_fade(numSteps, gFade[x], &rgbs[x]);
  118.     }
  119.  
  120.      // fade each device
  121.      // I know this is unreadable (dontcha love C?), the idea is to count down on
  122.      // fadeout and count up on fade in.
  123.      for (stepCount = fadeOut ? numSteps : 0; fadeOut ? stepCount >= 0 : stepCount < numSteps; fadeOut ? stepCount-- : stepCount++)
  124.      {
  125.          for (x = 0; x < numDevices; x++)
  126.          {
  127.              SetGDevice(gdHdls[x]);
  128.             if (fadeOut)
  129.                 fade_out(stepCount, gFade[x], rgbs[x]);
  130.             else
  131.                 fade_in(stepCount, gFade[x], gOrig[x], rgbs[x]);
  132.         }
  133.     }
  134.     
  135.     // restore each devices clut, and dispose of temp memory
  136.     for (x = 0; x < numDevices; x++)
  137.     {
  138.         SetGDevice(gdHdls[x]);
  139.         restore_clut(gFade[x], gOrig[x]);
  140.         DisposeHandle((Handle)gOrig[x]);
  141.     }        
  142.     
  143.     // set original device
  144.     SetGDevice(oldDev);    
  145. }
  146.  
  147. /*********************************** fade_to_clut *******************************/
  148. pascal void fade_to_clut(long numSteps, CTabHandle destTab, GDHandle aGDevice )
  149. {
  150. CTabHandle    srcTab = (**(**aGDevice).gdPMap).pmTable; // get the monitor’s current clut
  151. long        redDelta[MAXCOLORS];    // We want the range for each color to be of an
  152. long        greenDelta[MAXCOLORS];    // unsigned short, but we need negative numbers.
  153. long        blueDelta[MAXCOLORS];    // So these longs are the solution.
  154. long        difference;                // used to clear up clutter in the code
  155. long        i;                        // to cycle trough for loops
  156. long        colorIndex;                // to cycle through arrays
  157. GDHandle    oldGDevice;
  158.  
  159.     oldGDevice = GetGDevice(); // save the old
  160.  
  161.     SetGDevice( aGDevice );  // set it to the monitor to be faded
  162.  
  163.     /**** Set up the deltas ****/
  164.     for( i=0; i <= (**destTab).ctSize; i++ )
  165.     {    /*    This is what I am thinking: take the difference between the two colors and divide
  166.             it by the number of steps (numSteps). So we will have a number that can be added
  167.             to the source numSteps times and have it end up equaling the destination.
  168.         */
  169.   
  170.         difference = ( (long)(**srcTab).ctTable[i].rgb.red - (long)(**destTab).ctTable[i].rgb.red );
  171.         redDelta[i] = difference / (long)numSteps;
  172.   
  173.           difference = ( (long)(**srcTab).ctTable[i].rgb.green - (long)(**destTab).ctTable[i].rgb.green );
  174.           greenDelta[i] = difference / (long)numSteps;
  175.   
  176.         difference = ( (long)(**srcTab).ctTable[i].rgb.blue - (long)(**destTab).ctTable[i].rgb.blue );
  177.         blueDelta[i] = difference / (long)numSteps;
  178.     }
  179.  
  180.     /**** Do the fade ****/
  181.     for( i = 0; i < numSteps; i++ )
  182.     {
  183.         for( colorIndex = 0; colorIndex <= (**destTab).ctSize; colorIndex++ )
  184.         { // make the source more and more like the dest
  185.             (**srcTab).ctTable[colorIndex].rgb.red -= redDelta[colorIndex];
  186.             (**srcTab).ctTable[colorIndex].rgb.green -= greenDelta[colorIndex];
  187.             (**srcTab).ctTable[colorIndex].rgb.blue -= blueDelta[colorIndex];
  188.         }
  189.   
  190.         SetEntries( 0, (**srcTab).ctSize, (ColorSpec *)&(**srcTab).ctTable );
  191.     }
  192.  
  193.     SetEntries( 0, (**destTab).ctSize, (ColorSpec *)&(**destTab).ctTable ); // set it to the dest, just in case
  194.     (**srcTab).ctSeed = (**destTab).ctSeed;    // set the ctSeed as well!
  195.     MakeITable( nil, nil, 0 );
  196.  
  197.     SetGDevice( oldGDevice ); // return it back to it’s old state
  198. }
  199.  
  200. pascal void fade_to_color(long numSteps, RGBColor* destColor, GDHandle aGDevice )
  201. {
  202. CTabHandle    newColors;
  203. short        x;
  204.  
  205.     // get copy of the current color table
  206.     copy_gdevice_clut(aGDevice,&newColors);
  207.  
  208.     // make the color table all one color
  209.     for( x = 0; x <= (**newColors).ctSize; x++ )
  210.         (**newColors).ctTable[x].rgb = *destColor;
  211.         
  212.     // change the ctSeed so it is different than original
  213.     (**newColors).ctSeed = GetCTSeed();
  214.  
  215.     // fade to the custom color table
  216.     fade_to_clut(numSteps,newColors,aGDevice);
  217.  
  218.     // dispose color table
  219.     DisposeHandle((Handle)newColors);
  220. }
  221.  
  222. pascal void copy_gdevice_clut(GDHandle aGDevice, CTabHandle* copyOfClut)
  223. {
  224. CTabHandle    srcTab = (**(**aGDevice).gdPMap).pmTable; // get the monitor’s current clut
  225.  
  226.     HandToHand((Handle*)&srcTab);
  227.     *copyOfClut = srcTab;
  228. }
  229.  
  230. //===== PRIVATE FUNCTIONS =====//
  231.  
  232. /********************************** copy_cluts **********************************/
  233. static
  234. void copy_cluts(GDHandle hGD, CTabHandle* gFade, CTabHandle* gOrig, short arrayPos)
  235. {    
  236. Handle        gTempH;            //  temporary handle to copy 'clut'
  237.  
  238.     *gFade = (*(*hGD)->gdPMap)->pmTable;
  239.     gTempH = (Handle) (*(*hGD)->gdPMap)->pmTable;
  240.     HandToHand(&gTempH);
  241.     *gOrig = (CTabHandle) gTempH;
  242.     
  243.     HLock((Handle) *gFade);
  244.     HLock((Handle) *gOrig);
  245. }
  246.  
  247. /*********************************** calc_fade **********************************/
  248. static
  249. void calc_fade(long numSteps, CTabHandle gFade, FadeValues *rgbs)
  250. {
  251.     short    i;
  252.     
  253.     for (i = 0; i <= (*gFade)->ctSize; i++)
  254.     {
  255.         rgbs->reds[i]   = (*gFade)->ctTable[i].rgb.red   / numSteps;
  256.         rgbs->greens[i] = (*gFade)->ctTable[i].rgb.green / numSteps;
  257.         rgbs->blues[i]  = (*gFade)->ctTable[i].rgb.blue  / numSteps;
  258.     }
  259. }
  260.  
  261. /*********************************** fade_out ***********************************/
  262. static
  263. void fade_out(long fadeLevel, CTabHandle gFade, FadeValues rgbs)
  264. {
  265.     short     i;
  266.     
  267.     for (i = 0; i <= (*gFade)->ctSize; i++)
  268.     {
  269.         if ((*gFade)->ctTable[i].rgb.red   > rgbs.reds[i])
  270.             (*gFade)->ctTable[i].rgb.red   -= rgbs.reds[i];
  271.         if ((*gFade)->ctTable[i].rgb.green > rgbs.greens[i])
  272.             (*gFade)->ctTable[i].rgb.green -= rgbs.greens[i];
  273.         if ((*gFade)->ctTable[i].rgb.blue  > rgbs.blues[i])
  274.             (*gFade)->ctTable[i].rgb.blue  -= rgbs.blues[i];
  275.     }
  276.     SetEntries(0,  (*gFade)->ctSize, (*gFade)->ctTable);
  277.     
  278.     if (fadeLevel == 0)
  279.         black_out(gFade);
  280. }
  281.  
  282. /************************************ fade_in ***********************************/
  283. static
  284. void fade_in(long fadeLevel, CTabHandle gFade, CTabHandle gOrig, FadeValues rgbs)
  285. {
  286.     short     i;
  287.     
  288.     if (fadeLevel == 0)
  289.         black_out(gFade);
  290.  
  291.     for (i = 0; i <= (*gFade)->ctSize; i++)
  292.     {
  293.         if ((*gFade)->ctTable[i].rgb.red   < (*gOrig)->ctTable[i].rgb.red)
  294.             (*gFade)->ctTable[i].rgb.red   += rgbs.reds[i];
  295.         if ((*gFade)->ctTable[i].rgb.green < (*gOrig)->ctTable[i].rgb.green)
  296.             (*gFade)->ctTable[i].rgb.green += rgbs.greens[i];
  297.         if ((*gFade)->ctTable[i].rgb.blue  < (*gOrig)->ctTable[i].rgb.blue)
  298.             (*gFade)->ctTable[i].rgb.blue  += rgbs.blues[i];
  299.     }
  300.     SetEntries(0, (*gFade)->ctSize, (*gFade)->ctTable);
  301. }
  302.  
  303. /*********************************** black_out **********************************/
  304. static
  305. void black_out(CTabHandle gFade)
  306. {
  307.     short     i;
  308.     
  309.     for (i = 0; i <= (*gFade)->ctSize; i++)
  310.     {
  311.         (*gFade)->ctTable[i].rgb.red   = 0;
  312.         (*gFade)->ctTable[i].rgb.green = 0;
  313.         (*gFade)->ctTable[i].rgb.blue  = 0;
  314.     }
  315.     SetEntries(0, (*gFade)->ctSize, (*gFade)->ctTable);
  316. }
  317.  
  318. /********************************** restore_clut ********************************/
  319. static
  320. void restore_clut(CTabHandle gFade, CTabHandle gOrig)
  321. {
  322.     short     i;
  323.     
  324.     for (i = 0; i <= (*gFade)->ctSize; i++)
  325.     {
  326.         (*gFade)->ctTable[i].rgb.red   = (*gOrig)->ctTable[i].rgb.red;
  327.         (*gFade)->ctTable[i].rgb.green = (*gOrig)->ctTable[i].rgb.green;
  328.         (*gFade)->ctTable[i].rgb.blue  = (*gOrig)->ctTable[i].rgb.blue;
  329.     }
  330.     (*gFade)->ctSeed = (*gOrig)->ctSeed; // restore the ctSeed too!
  331.     MakeITable(nil, nil, 0);
  332.     
  333.     HUnlock((Handle) gFade);
  334.     HUnlock((Handle) gOrig);
  335. }
  336.